简介
BeanFactory 是 Spring 框架最核心的接口,它提高了高级 IOC 的配置机制。BeanFactory 使管理不同类型的 Java 对象成为可能,ApplicationContext 建立在 BeanFactory 的基础之上,提供了更多面向应用的功能,提供了国际化支持和框架事件体系,更易于创建实际应用。BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身,ApplicationContext 面向使用 Spring 框架的开发者。
BeanFactory
BeanFactory 提供了 Spring IOC 的基础功能,但它只能在第三方框架中直接使用。和 BeanFactory 相关的接口,如 BeanFactoryAware,InitializingBean,DisposableBean,仍然存在于 Spring 中用于与 Spring 集成的大量第三方框架向后兼容的作用。BeanFactory 通常使用在运行于资源有限(内存消耗严重)的嵌入式应用中。
使用 BeanFactory 实现注册一个后处理器(PostProcessor):
123456DefaultListableBeanFactory factory = new DefaultListableBeanFactory();// populate the factory with bean definitions// now register any needed BeanPostProcessor instancesMyBeanPostProcessor postProcessor = new MyBeanPostProcessor();factory.addBeanPostProcessor(postProcessor);// now start using the factory使用 BeanFactory 实现注册一个 BeanFactoryPostProcessor:
12345678DefaultListableBeanFactory factory = new DefaultListableBeanFactory();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));// bring in some property values from a Properties filePropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();cfg.setLocation(new FileSystemResource("jdbc.properties"));// now actually do the replacementcfg.postProcessBeanFactory(factory);
ApplicationContext
ApplicationContext 继承自 BeanFactory,提供了更多面向实际应用的功能。在 BeanFactory 中,很多功能需要以编程的方式实现,而在 ApplicationContext 中则可以通过配置的方式实现。
下图为 ApplicationContext 的继承体系图:
ApplicationContext 的主要实现类是 ClassPathXmlApplicationContext,FileSystemXmlApplicationContext 和 AnnotationConfigApplicationContext,第一个默认从类路径加载配置文件,第二个默认从文件系统中装载配置文件,第三个可直接传入注解类,通过 register(Class…) 注册类或 scan(String…) 扫描路径 classpath 逐个注册类。
如上图所示,ApplicationContext 继承了 HierarchicalBeanFactory 和 ListableBeanFactory 接口,在此之上还通过其他的接口扩展了 BeanFactory 的功能。这类接口包括:
- ApplicationEventPublisher:让容器拥有发布 ApplicationContext 事件的功能,包括容器启动时间、关闭事件等。实现了 ApplicationListener 事件监听接口的 Bean 可以接收到容器事件,并对事件进行响应处理。在 ApplicationContext 抽象实现类 AbstractApplicationContext 中,可以发现存在一个 ApplicationEventMulticaster,它负责保存所有监听器,以便在容器产生 ApplicationContext 事件时通知这些事件监听者。
- MessageSource:为应用提供 i18n 国际化消息访问的功能。
- ResourcePatternResolver:所有 ApplicationContext 实现类都实现了通过 Ant 风格的资源文件路径装载 Spring 的配置文件。
- Lifecycle:该接口于 Spring2.0 加入,提供了 start() 和 stop() 两个方法,主要用于控制异步处理过程。具体使用时,该接口同时被 ApplicationContext 实现及具体 Bean 实现,ApplicationContext 会将 start/stop 的信息传递给容器中所有实现了该接口的 Bean,以达到管理和控制 JMX、任务调度等目的。
ConfigurableApplicationContext 继承自 ApplicationContext,增加了两个主要的方法:refresh() 和 close(),让 ApplicationContext 具有启动、刷新和关闭上下文的能力。在 ApplicationContext 关闭时,调用 refresh 可启动 ApplicationContext;在启动状态下调用,则清除缓存并重新装载配置信息。调用 close 关闭 ApplicationContext。
ApplicationContext 的初始化:
ApplicationContext 在实例化后和 BeanFactory 一样调用 getBean(beanName) 返回 Bean;在初始化时,BeanFactory 初始化容器时并未实例化 Bean 直至第一次访问 Bean,ApplicationContext 在初始化上下文时实例化所有单实例的 Bean。和基于 XML 文件配置方式的相比,类注解的配置方式可以很容易地让开发者控制 Bean 的初始化过程。
配置文件在类路径下,优先使用 ClassPathXmlApplicationContext,“com/example/context/beans.xml” 等同于 “classpath:com/example/context/beans.xml”:
1234ApplicationContext ctx = newClassPathXmlApplicationContext("com/example/context/beans.xml");ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{ "com/beans1.xml", "com/beans2.xml" });配置文件在类路径下,优先使用 FileSystemXmlApplicationContext,“com/example/context/beans.xml” 等同于 “file:com/example/context/beans.xml”:
12ApplicationContext ctx = newFileSystemXmlApplicationContext("com/example/context/beans.xml");需要解析的是注解类,使用 AnnotationConfigApplicationContext:
Bean 类:
1234567891011121314151617181920package com.lake.context;public class Car {private String brand;private int maxSpeed;public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public int getMaxSpeed() {return maxSpeed;}public void setMaxSpeed(int maxSpeed) {this.maxSpeed = maxSpeed;}}带注解的 POJO 类:
12345678910111213package com.lake.context;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;public class Beans {"car")(name =public Car buildCar() {Car car = new Car();car.setBrand("奔驰");car.setMaxSpeed(300);return car;}}通过带 @Configuration 的 POJO 类启动容器:
12345678910package com.lake.context;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AnnotationApplicantionContext {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(Beans.class);Car car = context.getBean("car", Car.class);car.getBrand();}}
WebApplicationContext
WebApplicationContext 为 Web 应用而准备,它允许从相对于 Web 根目录的路径中装载配置文件完成初始化工作。Spring 提供了工具类 WebApplicationContextUtils,通过 getWebApplicationContext(ServletContext sc) 获取 WebApplicationContext 实例。
ConfigurableWebApplicationContext 继承自 WebApplicationContext,它允许通过配置的方式实例化 WebApplicationContext,它有两个重要的方法:
- setServletContext(ServletContext servletContext):为 Spring 设置 WebApplicationContext。
- setConfigLocations(String[] configLocations):设置 Spring 配置文件地址,相对于 Web 根目录,如 /WEB-INF/lake-dao.xml,/WEB-INF/lake-service.xml 等。但用户也可使用带资源类型前缀的地址,如 classpath:com/example/context/beans.xml 等。
WebApplicationContext 初始化
WebApplicationContext 需要 ServletContext 实例,它必须在拥有 Web 容器的情况下才能完成启动工作,和通常的 Web 开发类似,在 web.xml 中配置自启动的 Servlet 或容器监听器(ServletContextListener),即可完成启动 Spring WebApplicationContext 的工作。
Spring 提供了用于启动 WebApplicationContext 的 Servlet 和 Web 容器监听器:
- org.springframework.web.context.ContextLoaderServlet
- org.springframework.web.context.ContextLoaderListener
两者都实现了启动 WebApplicationContext 实例的逻辑,只要根据 Web 容器的具体情况选择其一,并在 web.xml 中完成配置即可。
ContextLoaderListener 启动 WebApplicationContext:
在不支持容器监听器的低版本 Web 容器中,使用 ContextLoaderServlet:
标准和自定义事件
ApplicationContext 通过 ApplicationEvent 和 ApplicationListener 接口提供事件处理,当某个 bean 实现了 ApplicationListener 接口时,当 ApplicationEvent 发布给 ApplicationContext 时,该 bean 会被告知。
标准事件
- ContextRefreshedEvent:当 ApplicationContext 被初始化或刷新时发布事件。这里的初始化是指所有的 beans 被加载,后处理器 beans 被检测并激活,单例被预实例化,ApplicationContext 对象已准备好并可用。当上下文关闭时,refresh 可以被多次触发,这样的 ApplicationContext 支持热刷新。XmlWebApplicationContext 支持热刷新,而 GenericApplicationContext 不支持。
- ContextStartedEvent:ApplicationContext 被启动时发布事件,使用 ConfigurableApplicationContext 接口的 start() 方法。这里的启动意味着 beans 接收一个显式的启动信号,该信号用于在显式的停止之后重新启动 beans,也可以用于启动没有被配置成自动启动的组件。
- ContextStoppedEvent:ApplicationContext 被停止时发布事件,使用 ConfigurableApplicationContext 接口的 stop() 方法。
- RequestHandledEvent:告知所有 beans 一个 HTTP 请求已被处理的特定的 web 事件,当请求完成时事件将会被发布,该事件只能通过 Spring 的 DispatcherServlet 应用于 Web 应用中。
自定义事件
自定义事件需要继承 Spring 的 ApplicationEvent 基类:
调用 ApplicationEventPublisher 的 publishEvent() 方法发布自定义的 ApplicationEvent,该类需要实现 ApplicationEventPublisherAware 接口并作为 bean 来注册。在配置期间,Spring 容器会检测到实现了 ApplicationEventPublisherAware 接口的 EmailService 并自动的调用 setApplicationEventPublisher() 方法。
创建一个实现 ApplicationListener 接口的类,并作为 bean 来注册,以此接受自定义的 ApplicationEvent。
下面的代码用于配置和注册上述的类:
当 emailService 的 sendEmail() 方法被调用时,如果有任何邮件需要被加入黑名单,那么自定事件 BlackListEvent 会被发布。blackListNotifier bean 被注册作为 ApplicationListener 并接收 BlackListEvent。
基于注解的事件监听器
|
|
异步监听器
|
|
顺序监听器
|
|